#include <stdio.h>
#include <stdlib.h>
#include <string.h>
#include <openssl/md5.h>
#include "mrss.h"

#include <openssl/bio.h>
#include <openssl/evp.h>
#include <math.h>

#define MSG_DIR "mensagens/"

//Encodes Base64
int Base64Encode(char* message, char** buffer) { //Encodes a string to base64
  BIO *bio, *b64;
  FILE* stream;
  int encodedSize = 4*ceil((double)strlen(message)/3);
  *buffer = (char *)malloc(encodedSize+1);

  stream = fmemopen(*buffer, encodedSize+1, "w");
  b64 = BIO_new(BIO_f_base64());
  bio = BIO_new_fp(stream, BIO_NOCLOSE);
  bio = BIO_push(b64, bio);
  BIO_set_flags(bio, BIO_FLAGS_BASE64_NO_NL); //Ignore newlines - write everything in one line
  BIO_write(bio, message, strlen(message));
  BIO_flush(bio);
  BIO_free_all(bio);
  fclose(stream);

  return (0); //success
}


static char *formata_html( unsigned char *original, unsigned char *resultado) {

  int i =0;
  int tamanho = strlen(original);
  char *token;
  char *sep = "\n";
  
  // Define var de retorno, e aloca memoria para ela, com folga

  //colocar <p> no inicio
  strcpy(resultado,"<p>");

  //chamar token()
  token = strtok(original,sep);
  while (token != NULL) {
    strcat(resultado, token);		// copia o token para res
    strcat(resultado, "</p><p>");	// copia strings
    token = strtok(NULL, sep);		// chama o token novamente
  }

  // tem um <p> sobrando, fechar
  strcat(resultado,"</p>");

}

static void print_md5 (unsigned char *hash) {

  int i;
  for (i = 0; i < MD5_DIGEST_LENGTH; i++) printf("%02x",hash[i]);

}

static char *md52str(unsigned char *md5,unsigned  char *md5txt) {

  int i;
  for (i = 0; i < MD5_DIGEST_LENGTH; i++) sprintf(&md5txt[i*2],"%02x",md5[i]);
  return md5txt;
}

int doesFileExist(const char* filename) {
  FILE* fptr = fopen(filename, "r");
  if (fptr != NULL)
  {
    fclose(fptr);
    return 1;
  }
  return 0;
}

static void escreve_arq (char *md5, mrss_item_t *item, char *titulo, char *BLOG) {

  FILE *arq;
  char *mode = "w";
  char temp[128];

  char subject[1024];
  char* subject_b64;	// se comentar da erro no corpo da mensagem. Deus sabe por que...
  char* sub64;

  char *mensagem;

  unsigned char subject_md5_ascii[MD5_DIGEST_LENGTH*2];
  unsigned char subject_md5[MD5_DIGEST_LENGTH];
  MD5_CTX context;

  mensagem = (char*) malloc(2*strlen(item->description));

  formata_html(item->description,mensagem);

  sprintf(temp, "%s%s",MSG_DIR,md5);

  // Montando o arquivo do mail - texto plano
  arq = fopen(temp, "w");

  // Montando var para md5 do subject
  sprintf(subject, "%s %s", BLOG, titulo);
// Converte para base64 o subject
  Base64Encode(subject, &sub64);

  // md5 do subject
  MD5_Init(&context);
  MD5_Update(&context, subject, strlen(subject));
  MD5_Final(subject_md5, &context);

  md52str(subject_md5,subject_md5_ascii);
  fprintf(arq, "To: invest@calvin.arroway.org");
  fprintf(arq, "\nSubject: =?utf-8?B?%s?=",sub64);
  fprintf(arq, "\nMessage-ID: <%s@arroway.org>", subject_md5_ascii);
  fprintf(arq, "\nReferences: <%s@arroway.org>", subject_md5_ascii);
  fprintf(arq, "\nThread-Topic: %s", titulo);
  fprintf(arq, "\nContent-Type: text/html; charset=UTF-8");
  fprintf(arq, "\n\n<!DOCTYPE html>");
  fprintf(arq, "\n<html>");
  fprintf(arq, "\n <head>");
  fprintf(arq, "\n  <title>%s</title>");
  fprintf(arq, "\n </head>");
  fprintf(arq, "\n<body>");
  fprintf(arq, "\n<h3>%s por %s</h3>",titulo,item->other_tags->value);
  fprintf(arq, "\n%s",mensagem);
  fprintf(arq, "\n\n<p><a href=\"%s\" /a> Link </p>",item->link);
  fprintf(arq, "\n </body>");
  fprintf(arq, "\n</html>");

  fclose(arq);

  free(mensagem);
}

int main (int argc, char **argv) {

  mrss_t *data;
  mrss_error_t ret;
  mrss_item_t *item;
  CURLcode code;
  unsigned char hash[MD5_DIGEST_LENGTH];
  unsigned char md5str[MD5_DIGEST_LENGTH*2];

  const char HOME_DIR[50];
  char CAMINHO[100];

  FILE *tempFile;
  MD5_CTX mdContext;
  int bytes, i;
  unsigned char block[1024];

  char titulo[512];
  char BLOG[32];

  if (argc != 3)
    {
      fprintf (stderr,
	       "Usage:\n\t%s url_rss\n\nExample:\n\t%s http://ngvision.org/rss|file.rss\n\n BLOG",
	       argv[0], argv[0]);
      return 1;
    }

  if (!strncmp (argv[1], "http://", 7) || !strncmp (argv[1], "https://", 8))
    ret = mrss_parse_url_with_options_and_error (argv[1], &data, NULL, &code);
  else
    ret = mrss_parse_file (argv[1], &data);

  if (ret)
    {
      fprintf (stderr, "MRSS return error: %s\n",
	       ret ==
	       MRSS_ERR_DOWNLOAD ? mrss_curl_strerror (code) :
	       mrss_strerror (ret));
      return 1;
    }

  strcpy(BLOG,argv[2]);

  item = data->item;
  while (item)
    {

    // Escrever arquivo temp
    tempFile = fopen("temp_msg","w");

    // Escrever arquivo
    fprintf(tempFile, "%s", item->description);
    fclose (tempFile);

    tempFile = fopen("temp_msg","r");

    MD5_Init (&mdContext);
    while ((bytes = fread (block, 1, 1024, tempFile)) != 0)
        MD5_Update (&mdContext, block, bytes);
    MD5_Final (hash,&mdContext);
    fclose (tempFile);

    // Tratando o subject
    memset(titulo,0,sizeof(titulo));
    // Retirando o tamanho do tag->value somado a 5, que eh o tamanho de dois espacos e 
    // a palavra "por"
    strncpy(titulo,item->title, (strlen(item->title)-strlen(item->other_tags->value)-5) );

    md52str (hash,md5str);

    CAMINHO[0]='\0';
    strcat(CAMINHO, MSG_DIR);
    strcat(CAMINHO,md5str);

      // Tratamento
      // Tem ja o arquivo ?
      if (doesFileExist(CAMINHO)) {

        // Mensagem ja existente
      } else {

        //Manda mail
        // Tratar a mensagem


        // Simplesmente escrevendo o arquivo
        // Usando o titulo alterado acima
        escreve_arq(md5str, item, titulo, BLOG);
      }

      item = item->next;

    }

  mrss_free (data);

  return 0;
}
